package view;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Arrays;
import java.util.List;

import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;

import model.EventType;
import model.Prediction;
import modelInterfaces.IEventType;
import modelInterfaces.IPrediction;
import modelInterfaces.ISubject;
import utils.Codes;
import utils.Messages;
import utils.Validations;
import viewInterfaces.IViewRunSetup;
import controller.ControllerDBConnectionSetup;
import controller.ControllerRunSetup;
import controllerInterfaces.IControllerDBConnectionSetup;
import controllerInterfaces.IControllerRunSetup;

public class ViewRunSetup extends JFrame implements IViewRunSetup {
	
	/** MVC++ Controller
	* @see ControllerRunSetup*/	
	private IControllerRunSetup myController;
	
	/** Textfield about number of items to recommender*/
	private JTextField textFieldItemsAmount;
	
	/** TextArea about recommender output*/
	private JTextArea textAreaRecommenderOutput;
	
	/** target users list */
	private JList listUsers;
	
	/** target events types list*/
	private JList listEventTypes;


	/**
	 * Class Constructor creates the frame.
	 */
	public ViewRunSetup() {
		setTitle("Run Setup");
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosed(WindowEvent arg0) {
				close();
			}
		});
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setBounds(100, 100, 503, 491);
		JPanel contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		
		JPanel panelRunOptions = new JPanel();
		panelRunOptions.setBorder(new TitledBorder(null, "Run options", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		
		JPanel panelRecommenderOutput = new JPanel();
		panelRecommenderOutput.setBorder(new TitledBorder(null, "Recommender output", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		GroupLayout gl_contentPane = new GroupLayout(contentPane);
		gl_contentPane.setHorizontalGroup(
			gl_contentPane.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_contentPane.createSequentialGroup()
					.addComponent(panelRunOptions, GroupLayout.DEFAULT_SIZE, 228, Short.MAX_VALUE)
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addComponent(panelRecommenderOutput, GroupLayout.DEFAULT_SIZE, 239, Short.MAX_VALUE))
		);
		gl_contentPane.setVerticalGroup(
			gl_contentPane.createParallelGroup(Alignment.TRAILING)
				.addGroup(gl_contentPane.createSequentialGroup()
					.addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING)
						.addComponent(panelRecommenderOutput, GroupLayout.DEFAULT_SIZE, 452, Short.MAX_VALUE)
						.addComponent(panelRunOptions, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
					.addGap(0))
		);
		
		textAreaRecommenderOutput = new JTextArea();
		textAreaRecommenderOutput.setEditable(false);
		textAreaRecommenderOutput.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
		GroupLayout gl_panelRecommenderOutput = new GroupLayout(panelRecommenderOutput);
		gl_panelRecommenderOutput.setHorizontalGroup(
			gl_panelRecommenderOutput.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panelRecommenderOutput.createSequentialGroup()
					.addContainerGap()
					.addComponent(textAreaRecommenderOutput, GroupLayout.DEFAULT_SIZE, 192, Short.MAX_VALUE)
					.addContainerGap())
		);
		gl_panelRecommenderOutput.setVerticalGroup(
			gl_panelRecommenderOutput.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panelRecommenderOutput.createSequentialGroup()
					.addContainerGap()
					.addComponent(textAreaRecommenderOutput, GroupLayout.DEFAULT_SIZE, 287, Short.MAX_VALUE)
					.addContainerGap())
		);
		panelRecommenderOutput.setLayout(gl_panelRecommenderOutput);
		
		JLabel lblItemsAmount = new JLabel("Items Amount:");
		lblItemsAmount.setToolTipText("Items Amount to Recommend");
		
		textFieldItemsAmount = new JTextField();
		textFieldItemsAmount.setColumns(10);
		
		JLabel lblCurrentUser = new JLabel("Current User:");
		
		JButton btnRun = new JButton("Run");
		btnRun.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (Validations.isValidRunSetup(textFieldItemsAmount.getText(), listUsers, listEventTypes)) {
					myController.SetCurrentUser((ISubject) listUsers.getSelectedValue());
					myController.SetItemAmountToRecommend(Integer.valueOf(textFieldItemsAmount.getText()));
					myController.SetEventTypes( (List<IEventType>) listEventTypes.getSelectedValuesList());
					myController.run();
				}
				else
				{
					renderError(Codes.runSetup, Messages.runSetup);
				}
			}
		});
		
		JScrollPane scrollPaneUsers = new JScrollPane();
		
		JScrollPane scrollPaneEventTypes = new JScrollPane();
		
		JLabel lblEventTypes = new JLabel("Event types:");
		GroupLayout gl_panelRunOptions = new GroupLayout(panelRunOptions);
		gl_panelRunOptions.setHorizontalGroup(
			gl_panelRunOptions.createParallelGroup(Alignment.TRAILING)
				.addGroup(gl_panelRunOptions.createSequentialGroup()
					.addContainerGap()
					.addGroup(gl_panelRunOptions.createParallelGroup(Alignment.LEADING)
						.addComponent(btnRun, Alignment.TRAILING)
						.addGroup(gl_panelRunOptions.createSequentialGroup()
							.addComponent(lblItemsAmount)
							.addGap(10)
							.addComponent(textFieldItemsAmount, GroupLayout.DEFAULT_SIZE, 115, Short.MAX_VALUE))
						.addGroup(gl_panelRunOptions.createSequentialGroup()
							.addGroup(gl_panelRunOptions.createParallelGroup(Alignment.LEADING)
								.addComponent(lblCurrentUser)
								.addComponent(lblEventTypes))
							.addGap(15)
							.addGroup(gl_panelRunOptions.createParallelGroup(Alignment.LEADING)
								.addComponent(scrollPaneUsers, GroupLayout.DEFAULT_SIZE, 115, Short.MAX_VALUE)
								.addComponent(scrollPaneEventTypes, GroupLayout.DEFAULT_SIZE, 115, Short.MAX_VALUE))))
					.addContainerGap())
		);
		gl_panelRunOptions.setVerticalGroup(
			gl_panelRunOptions.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panelRunOptions.createSequentialGroup()
					.addContainerGap()
					.addGroup(gl_panelRunOptions.createParallelGroup(Alignment.BASELINE)
						.addComponent(lblItemsAmount)
						.addComponent(textFieldItemsAmount, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addGroup(gl_panelRunOptions.createParallelGroup(Alignment.LEADING)
						.addComponent(lblCurrentUser)
						.addComponent(scrollPaneUsers, GroupLayout.DEFAULT_SIZE, 249, Short.MAX_VALUE))
					.addPreferredGap(ComponentPlacement.RELATED)
					.addGroup(gl_panelRunOptions.createParallelGroup(Alignment.BASELINE)
						.addComponent(scrollPaneEventTypes, GroupLayout.DEFAULT_SIZE, 97, Short.MAX_VALUE)
						.addComponent(lblEventTypes))
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(btnRun)
					.addGap(6))
		);
		
		listEventTypes = new JList();
		scrollPaneEventTypes.setViewportView(listEventTypes);
		
		listUsers = new JList();
		listUsers.setBorder(null);
		listUsers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		scrollPaneUsers.setViewportView(listUsers);
		panelRunOptions.setLayout(gl_panelRunOptions);
		contentPane.setLayout(gl_contentPane);
	}


	/**
	 * Show the frame
	 */	
	
	public void render() {
		this.setVisible(true);
	}


	/**
	 * Show error dialog
	 * @param code	error code
	 * @param message	error message
	 */	
	
	public void renderError(int code, String message) {
		javax.swing.JOptionPane.showMessageDialog(this, code + " - " + message, "Error",javax.swing.JOptionPane.ERROR_MESSAGE);
	}


	/**
	 * Close frame
	 */
	
	public void close() {
		dispose();		
	}


	/**
	 * Set the MVC++ Controller Class for this View.</br>
	 * ControllerDBConnectionSetup is manipulable through {@link IControllerDBConnectionSetup} interface
	 * @param	controller	MVC++ Controller
	 * @see	ControllerDBConnectionSetup
	 * @see IControllerDBConnectionSetup
	 */		
	public void setController(IControllerRunSetup controller) {
		this.myController = controller;
	}


	/**
	 * Set the list of subject or users in current JList</br>
	 * Each of the set {@link User} is manipulable through its {@link IUser} interface.
	 * @param	userList	list of {@link User}
	 * @see 	IUser
	 * @see		User
	 */		
	public void setUserList(List<ISubject> userList) {
		listUsers.setListData(userList.toArray());
	}


	
	/**
	 * Block frame.
	 */
	public void blockFrame()
	{
		this.setEnabled(false);
	}


	/**
	 * Unblock frame.
	 */
	public void unBlockFrame() {
		this.setEnabled(true);
	}

	
	/**
	 * Set the list of predictions in current TextArea</br>
	 * Each of the set {@link Prediction} is manipulable through its {@link IPrediction} interface.
	 * @param	predictionList	list of {@link Prediction}
	 * @see 	IPrediction
	 * @see		Prediction
	 */		
	public void setPredictions(List<IPrediction> predictionsList)
	{
		String text = "";
		for(IPrediction prediction : predictionsList)
		{
			text += "Item: "+ String.valueOf(prediction.getObject().getId()) + "\tValue :" + String.valueOf(prediction.getValue()) + "\n";
			textAreaRecommenderOutput.setText(text);
		}
	}


	/**
	 * Set the list of event type in current JList</br>
	 * Each of the set {@link EventType} is manipulable through its {@link IEventType} interface.
	 * @param	eventTypesList	list of {@link EventType}
	 * @see 	IEventType
	 * @see		EventType
	 */	
	public void setEventTypeList(List<IEventType> eventTypesList) {
		listEventTypes.setListData(eventTypesList.toArray());
	}
}
